# -*- coding:utf-8 -*-

# @File     :api_v1
# @Author   :Yupeng
# @Date     :2018/10/29 16:46

from apps.storage.models.data import DataMeta, DataContent
from apps.storage.models.pagination import MyPagination
from apps.storage.models.serializer import DataMetaSerializer
from apps.storage.models.template import Template
from apps.storage.models.dataset import DataSet
from apps.storage.models.material import MaterialCategory

from django.utils.translation import ugettext as _
from django.core.paginator import PageNotAnInteger, EmptyPage, Paginator
from django.db.models import Count
from django.contrib.postgres.search import SearchVector
from django.db.models import Q

from hte.utils.general import *
from hte.error.models import HTEError, HTEException
from .core.cache import get_full_text_cache, get_template_cache, set_full_text_cache, set_template_cache
from .core.query_tree import QuerySortField
from hte.utils.general import json_response
from .core.query_tree import QuickSimpleFullTextQuery, MetaQuery
from .utils.serilizers.json import JSONHandler
from .utils.serilizers.common import DataMode
import datetime
from apps.mlplatform.views import FormatListCreateAPIView


# 这个api是我自己测试用的，其他组员请不必在意
@require_GET_api
def lyp_test(request: HttpResponse):
    from .core.es_handler import Transform
    data_metas = DataMeta.objects.all()
    from .core.es_handler import ElasticsearchManager
    ElasticsearchManager.update_all()
    # ElasticsearchManager.param_merge_insert_all()
    # ElasticsearchManager.


def _do_query(query_dict, sort_field, desc: bool):
    # data_query = query_dict.get('data')
    meta_query = query_dict.get('meta')  # 选择了元数据之后的检索
    text_query = query_dict.get('text')  # 没有选择元数据字段，直接默认的全文检索，填写检索信息后的检索
    queryset = None

    meta_ids = ()
    # 没有选择元数据，直接在默认全文检索的情况下在搜索框里输入了词条，词条在数据内容部分也能够搜索到
    if text_query and not meta_query:
        id_list = get_full_text_cache(str(text_query))
        if id_list is None:
            query = QuickSimpleFullTextQuery(False, str(text_query))
            id_list = query.query()
            set_full_text_cache(str(text_query), id_list)
        queryset = DataMeta.objects.filter(id__in=id_list)

    # 选择了元数据，并且在搜索框中输入了词条
    elif meta_query and text_query:
        # 这里规定能够用来搜索的元数据，以后可以扩充
        if meta_query in ['title', 'keywords', 'abstract', 'author', 'purpose']:
            pass
        else:
            raise HTEException(
                HTEError.BAD_METADATA(_('fdsafdsfadsaf')))  # ???
        id_list = get_full_text_cache(str(text_query))
        if id_list is None:
            query = MetaQuery(False, str(meta_query), str(text_query))
            id_list = query.query()
            set_full_text_cache(str(text_query), id_list)
        queryset = DataMeta.objects.filter(id__in=id_list)

    if queryset is None:
        queryset = DataMeta.objects.filter(id__in=meta_ids)

    if sort_field is QuerySortField.NO_SORTING:
        queryset = queryset.order_by(('-' if desc else '') + QuerySortField.DATA_CREATED_TIME.sql_name)
    elif sort_field != QuerySortField.NO_SORTING:
        queryset = queryset.order_by(('-' if desc else '') + sort_field.sql_name).select_related()
    return queryset


def _dataset_query(query_dict, sort_field, desc: bool):
    meta_query = query_dict.get('meta')  # 选择了元数据之后的检索
    text_query = query_dict.get('text')  # 没有选择元数据字段，直接默认的全文检索，填写检索信息后的检索
    queryset = None
    meta_ids = ()
    if text_query and not meta_query:
        id_list = get_full_text_cache(str(text_query))
        if id_list is None:
            q = Q(title__contains=text_query) | Q(author__real_name=text_query) | Q(purpose__contains=text_query)
            queryset = DataSet.objects.filter(q)

    elif text_query and meta_query:
        # 这里规定能够用来搜索的元数据，以后可以扩充
        if meta_query in ['title', 'author', 'purpose']:
            pass
        else:
            raise HTEException(
                HTEError.BAD_METADATA(_('fdsafdsfadsaf')))  # ???
        id_list = get_full_text_cache(str(text_query))
        if id_list is None:
            if meta_query == 'title':
                queryset = DataSet.objects.filter(title__contains=text_query)
            elif meta_query == 'author':
                queryset = DataSet.objects.filter(author__real_name=text_query)
            else:
                queryset = DataSet.objects.filter(purpose__contains=text_query)
    if queryset is None:
        queryset = DataSet.objects.all()

    if sort_field is QuerySortField.NO_SORTING:
        queryset = queryset.order_by(('-' if desc else '') + QuerySortField.DATASET_UPDATE_TIME.sql_name)
    elif sort_field != QuerySortField.NO_SORTING:
        queryset = queryset.order_by(('-' if desc else '') + sort_field.sql_name).select_related()
    return queryset


@require_POST_api
def query_view(request: HttpResponse):
    '''

    :param request:
    :return:
    '''
    # sort:排序字段，暂时以两种方式对搜索结果排序，1、按时间升序或降序。2、按author首字母升序或者降序
    sort = get_json_field_r(request, 'sort', str, allow_none=True, default='').lower()
    page = get_json_field_r(request, 'page', int, allow_none=True, default=1)
    desc = get_json_field_r(request, 'desc', bool, allow_none=True, default=True)  # 默认是降序排列
    year_filter = get_json_field_r(request, 'year_filter', str, allow_none=True, default='')
    domain_filter = get_json_field_r(request, 'domain_filter', int, allow_none=True, default=0)
    author_filter = get_json_field_r(request, 'author_filter', str, allow_none=True, default='')

    try:
        sort = QuerySortField(sort)  # 判断filter的值是不是QueryFilterField的几个枚举类型，不是就直接报错执行下面了
    except ValueError:
        sort = QuerySortField.DATA_CREATED_TIME

    # query_dict
    query_dict = get_json_field_r(request, 'query_dict', dict, allow_none=True, default={})
    query_set = _do_query(query_dict, sort, desc)
    if year_filter != '':
        query_set = query_set.filter(add_time__year__gte=year_filter)
    if domain_filter != 0:
        query_set = query_set.filter(category_id=domain_filter)
    if author_filter != '':
        query_set = query_set.filter(author_id=author_filter)

    this_year = datetime.datetime.now().year
    # 对搜索结果按照年份给出数量
    # year_num = [0, 0, 0, 0, 0]
    year_num = dict()
    year_num[this_year - 4] = len(query_set.filter(add_time__year__gte=this_year - 4))
    year_num[this_year - 3] = len(query_set.filter(add_time__year__gte=this_year - 3))
    year_num[this_year - 2] = len(query_set.filter(add_time__year__gte=this_year - 2))
    year_num[this_year - 1] = len(query_set.filter(add_time__year__gte=this_year - 1))
    year_num[this_year] = len(query_set.filter(add_time__year__gte=this_year))
    # 对搜索结果按照用户数量给出
    # author_num = dict()
    author_num = tuple(query_set.values('author_id').annotate(count=Count('author_id')).order_by('-count'))
    domain_num = tuple(query_set.values('category_id').annotate(count=Count('category_id')).order_by('-count'))
    for x in domain_num:
        x['name'] = MaterialCategory.objects.get(pk=x['category_id']).name
    paginator = Paginator(query_set, 5)
    try:
        result_page = paginator.page(page)
    except (PageNotAnInteger, EmptyPage):
        page = 1
        result_page = paginator.page(1)

    result = [x.to_dict(meta_only=True) for x in result_page]
    # 对mongodb中的各数据(元数据)的各字段合并导入
    for i in range(len(result)):
        template = Template.objects.get(pk=result[i].get('tid'))
        serializer = JSONHandler(mode=DataMode.WRITE, template=template)
        data_meta = DataMeta.objects.get(pk=result[i].get('id'))
        result[i]['content'] = serializer.data_to_dict(data_meta)
    if year_filter != '':
        year_num = dict()
        year_num[year_filter] = len(query_set.filter(add_time__year__gte=year_filter))
        return json_response(
            {
                'page_count': paginator.num_pages, 'page_num': page, 'total_count': paginator.count,
                'year_num': year_num, 'domain_num': domain_num, 'author_num': author_num, 'result': result
            }
        )
    else:
        return json_response(
            {
                'page_count': paginator.num_pages, 'page_num': page, 'total_count': paginator.count,
                'year_num': year_num, 'domain_num': domain_num, 'author_num': author_num, 'result': result
            }
        )


@require_POST_api
def dataset_query_view(request: HttpResponse):
    '''
    数据集搜索，两种搜索方式如下：
    1、按元数据检索：author,title,purpose
    2、全文检索：
    两种搜索都能对结果排序，排序可以按照：upload_time,update_time,ref_count
    :param request:
    :return:
    '''
    sort = get_json_field_r(request, 'sort', str, allow_none=True, default='').lower()
    page = get_json_field_r(request, 'page', int, allow_none=True, default=1)
    desc = get_json_field_r(request, 'desc', bool, allow_none=True, default=True)  # 默认是降序排列

    try:
        sort = QuerySortField(sort)  # 判断filter的值是不是QueryFilterField的几个枚举类型，不是就直接报错执行下面了
    except ValueError:
        sort = QuerySortField.DATASET_UPDATE_TIME

    query_dict = get_json_field_r(request, 'query_dict', dict, allow_none=True, default={})
    # query_set = _dataset_query(query_dict, sort, desc)
    # 简单搜索实现的测试
    query_set = _dataset_query(query_dict, sort, desc)

    paginator = Paginator(query_set, 5)

    try:
        result_page = paginator.page(page)
    except (PageNotAnInteger, EmptyPage):
        page = 1
        result_page = paginator.page(1)
    result = [x.to_dict() for x in result_page]
    return json_response(
        {'page_count': paginator.num_pages, 'page_num': page, 'result': result, 'total_count': paginator.count}
    )


# fsch 2019-2-28
class hot_searched(FormatListCreateAPIView):
    serializer_class = DataMetaSerializer
    pagination_class = MyPagination
    # page_size = 5  修改
    MyPagination.page_size = 20

    import time
    import datetime
    today = datetime.date.today()
    # print(today)
    before = today - datetime.timedelta(days=7)
    before_start_time = int(time.mktime(time.strptime(str(before), '%Y-%m-%d')))

    # print(before)
    # print(before_start_time)
    # print(time.time())

    def get_queryset(self, time=before):
        # queryset = DataMeta.objects.filter(views__gte=5).order_by('-add_time')
        queryset = DataMeta.objects.filter(add_time__gte=time).order_by('-views')[:20]
        # print(queryset)
        return queryset

    # RuntimeWarning: DateTimeField DataMeta.add_time received a naive datetime while time zone is active
    #
    # settings中的USE_TZ = True的原因，把True改成False即可
